/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine - graphics/materials
// Copyright (c) 2015.  All Rights Reserved
//
// File:		AEMaterialTextures.h
// Author:		Gianluca Belardelli
// Date:		20/07/2015
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AEMATERIALTEXTURES_H_
#define _AEMATERIALTEXTURES_H_

/// \brief
///   Class that provides material textures for surfaces.
/// The VisSurface_cl class is derived from this class to inherit the material textures.
/// Furthermore, entities can replace material sets via the VisSurfaceTextureSet_cl class.
/// See VisBaseEntity_cl::SetCustomTextureSet
class AEMaterialTextures
{
// Members
public:

	/// \brief Enum specifying the usage of a texture.
	enum AETextureType
	{
		AETEXTURETYPE_DIFFUSE,      ///< The texture is used as a diffuse color map.
		AETEXTURETYPE_NORMALMAP,    ///< The texture is used as a normal map.
		AETEXTURETYPE_SPECULARMAP   ///< The texture is used as a specular map.
	};

	AEINT32 		m_nIndex; // index

	AEVector4f 		m_vcLightmapScaleOfs;    ///< xy = scale, zw = ofsset for uv => lightmap uv transform
	AETexturePtr 	m_spDiffuseTexture;      ///< the diffuse base texture of the material
	AETexturePtr 	m_spNormalMap;           ///< the normalmap texture of the material
	AETexturePtr 	m_spSpecularMap;         ///< the reflection map texture of the material
	AETexturePtr 	m_spModelLightmaps[4];   ///< 0: diffuse, 1-3: dot3 lightmaps

	//VisTextureAnimInstancePtr m_spDiffuseAnim; ///< texture animation instance for diffuse texture animation

	AEINT16 		m_sAuxiliaryTextureCount;
	AETexturePtr 	*m_spAuxiliaryTextures;

// Methods
public:
	/// \brief
	///   Constructor
	AE_FORCEINLINE AEMaterialTextures( void );

	AE_FORCEINLINE ~AEMaterialTextures( void );

	/** @name Access Textures */
	/// @{
	/// \brief
	///   Helper function to load and set a specific texture in this set.
	AE_DLLIMPEXP void SetTextureFile( AETextureType eType, const char *lpszFileName );

	/// \brief
	///   Helper function to return the texture filename string (or AENULL) of the texture in the specified texture slot.
	AE_DLLIMPEXP const char *GetTextureFile( AETextureType eType ) const;

	/// \brief
	///   Sets a specific texture object in the passed slot (diffuse/normalmap/specularmap). If the diffuse texture is changed (AETEXTURETYPE_DIFFUSE), then the texture animation instance is changed.
	AE_DLLIMPEXP void SetTexture( AETextureType eType, AETexture *lpTex );

	/// \brief
	///   Return the texture object in the specified texture slot.
	AE_DLLIMPEXP AETexture *GetTexture( AETextureType eType ) const;

	/// \brief
	///   Returns the file name of the base texture.
	AE_FORCEINLINE const char *GetBaseTexture( void ) const;

	/// \brief
	///   Returns the file name of the normal map texture.
	AE_FORCEINLINE const char *GetNormalMapTexture( void ) const;

	/// \brief
	///   Returns the file name of the specular texture.
	AE_FORCEINLINE const char *GetSpecularMapTexture( void ) const;

	/// \brief
	///   Returns a pointer to the base texture object that represents the diffuse base texture of the surface.
	AE_FORCEINLINE AETexture *GetBaseTextureObject( void ) const;

	/// \brief
	///   Sets the diffuse base texture on this material and creates a texture animation instance if the texture is animated.
	AE_DLLIMPEXP void SetBaseTexture( AETexture *lpTex );

	/// \brief
	///   Returns a pointer to the texture object that represents the normal map texture of the
	///   surface.
	AE_FORCEINLINE AETexture *GetNormalMapTextureObject( void ) const;

	/// \brief
	///   Returns the specular map texture object.
	AE_FORCEINLINE AETexture *GetSpecularMapTextureObject( void ) const;

	/// \brief
	///   Return the animation instance that is associated with the diffuse texture. If the diffuse texture is not animated, this function returns AENULL.
	/*VisTextureAnimInstance_cl *GetDiffuseTextureAnimation() const
	{
	return m_spDiffuseAnim;
	}*/

	/// \brief
	///   Returns the number of additional auxiliary textures associated with this material.
	AE_FORCEINLINE AEINT32 GetAuxiliaryTextureCount( void ) const;

	/// \brief
	///   Returns the additional auxiliary texture with index nIndex. The index must be in valid
	///   range [0..GetAuxiliaryTextureCount()-1].
	///
	/// \param nIndex
	///  The index of the auxiliary texture.
	///
	/// The return value can be AENULL is no auxiliary texture was set at the given index.
	AE_FORCEINLINE AETexture *GetAuxiliaryTexture( AEINT32 nIndex ) const;

	/// \brief
	///   Allocates an array of iCount auxiliary textures for this material. See GetAuxiliaryTexture or SetAuxiliaryTexture.
	///
	/// Auxiliary textures can be used to associate an arbitrary number of custom textures with a material without any hardcoded
	/// semantic (e.g. specular). Since auxiliary textures can be addressed in shader texture samplers, this is a convenient way
	/// to render geometry with identical shader setup but different texture sets.
	/// Allocating a new array does not preserve the old array in this material.
	///
	/// \param iCount
	///   new number of auxiliary textures. Can be 0
	AE_DLLIMPEXP void AllocateAuxiliaryTextures( AEINT32 nCount );

	/// \brief
	///   Associates an auxiliary texture with this material. The index must be in valid range defined by GetAuxiliaryTextureCount (which is the number of allocated textures via AllocateAuxiliaryTextures).
	AE_FORCEINLINE void SetAuxiliaryTexture( AEINT32 nIndex, AETexture *lpTexture ) const;

	/// @}
	/// \brief
	///   Assignment operator; assigns the texture smart pointers componentwise.
	AE_FORCEINLINE AEMaterialTextures &operator = ( const AEMaterialTextures &refOther );

	/// \brief
	///   Get the 0-based index of this entry in the owner's list.
	AE_FORCEINLINE AEINT32 GetIndex( void ) const;

	/// \brief
	///   Internal function - do not use
	AE_FORCEINLINE void SetIndex( AEINT32 nIndex );
};

#include "AEMaterialTextures.inl"

#endif // _AEMATERIALTEXTURES_H_
